package report_service

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"peilian-api/app/controllers/web_report"
	"peilian-api/app/global/common"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/errors"
	"peilian-api/app/global/log"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/app/services"
	"peilian-api/utils/date"
	"peilian-api/utils/function"
	"peilian-api/utils/sdk"
	"peilian-api/utils/tools"
	"strconv"
	"strings"
	"time"

	"github.com/SebastiaanKlippert/go-wkhtmltopdf"

	"github.com/gin-gonic/gin"
)

func init() {
	web_report.FetchEmotion = FetchEmotion
	web_report.FetchLanguageComment = FetchLanguageComment
	web_report.FetchMood = FetchMood
	web_report.FetchFocusTopicScore = FetchFocusTopicScore
	web_report.FetchEvaluationScore = FetchEvaluationScore
	web_report.FetchLogicScore = FetchLogicScore
	web_report.FetchCharacter = FetchCharacter
	web_report.FetchLabelsCache = FetchLabelsCache
}

func FindReportsByUID(uid int) ([]model.ReportList, *errors.ErrRes) {
	var reports []model.ReportList
	reportMs, err := new(tables.Session).FindReportsByUID(uid)
	if err != nil {
		return reports, errors.NewErrInfo(errors.DatabaseMysqlErrorCode, fmt.Errorf(errors.DatabaseMySqlOptionFail))
	}
	agent := new(tables.Agent)
	userQuery := variable.DB.MySQL.Model(&tables.User{}).Select("agent_id").Where("id=?", uid)
	variable.DB.MySQL.Where("id in (?)", userQuery).First(agent)
	for _, reportM := range reportMs {
		sessionM := reportM
		report := model.ReportList{}
		report.ID = reportM.ID
		if sessionM.Career == nil {
			continue
		}
		switch sessionM.Career.ReportType {
		case "web", "custom":
			report.URL = fmt.Sprintf(
				"%s/web-report?reportId=%d&careerId=%d",
				variable.Config.App.Prefix, sessionM.ID, sessionM.CareerID,
			)
		default:
			report.URL = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + reportM.Url
		}
		report.Status = reportM.Status
		report.IsRead = reportM.IsRead
		report.BeginDate = sessionM.CreatedAt
		report.Duration = date.SecondsSwitchTime(int(sessionM.FinishAt.Unix() - sessionM.CreatedAt.Unix()))
		report.CareerName = sessionM.Career.Name
		report.TotalScore = int(sessionM.TotalScore)
		report.FinishTime = sessionM.FinishAt
		report.ReportType = sessionM.Career.ReportType
		if strings.HasSuffix(reportM.Url, ".pdf") {
			report.ReportType = "pdf"
			report.URL = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + reportM.Url
		}
		report.IsShared = sessionM.IsShared
		report.ReportIsSync = sessionM.IsSync
		u := new(tables.User)
		variable.DB.MySQL.Select("IsSync").First(u, uid)
		if !u.IsSync {
			report.ReportIsSync = false
		}
		report.AgentIsSync = agent.IsSync
		reports = append(reports, report)
	}
	// 异步更新所有的报告提示信息
	go func() {
		variable.DB.Redis.Set(fmt.Sprintf(common.RedisNewReportEntranceKey, uid), "1", time.Hour*24*45)
		variable.DB.Redis.Set(fmt.Sprintf(common.RedisNewReportBannerKey, uid), "1", time.Hour*24*45)
		variable.DB.Redis.Set(fmt.Sprintf(common.RedisNewReportIconKey, uid), "1", time.Hour*24*45)
	}()

	return reports, nil
}

// 根据条件查询报告内容
func FindReportsByWhere(ct model.ReportListReq) ([]model.ReportList, *errors.ErrRes) {
	var reports []model.ReportList
	var uid = ct.Uid
	var whereStr = fmt.Sprintf("user_id = %d and finish_at <> '%s' ", uid, "0000-00-00 00:00:00")
	if ct.CondTime != nil && ct.StartTime != nil && ct.EndTime != nil {
		startTime := ct.StartTime.Format("2006-01-02 15:04:05")
		endTime := ct.EndTime.Format("2006-01-02 15:04:05")
		whereStr = fmt.Sprintf("%s and train_at >= '%s' and train_at <= '%s'", whereStr, startTime, endTime)
	}
	reportMs, err := new(tables.Session).FindReportsByWhereStr(whereStr)
	if err != nil {
		return reports, errors.NewErrInfo(errors.DatabaseMysqlErrorCode, fmt.Errorf(errors.DatabaseMySqlOptionFail))
	}
	agent := new(tables.Agent)
	userQuery := variable.DB.MySQL.Model(&tables.User{}).Select("agent_id").Where("id=?", uid)
	variable.DB.MySQL.Where("id in (?)", userQuery).First(agent)
	for _, reportM := range reportMs {
		sessionM := reportM
		report := model.ReportList{}
		report.ID = reportM.ID
		if sessionM.Career == nil {
			continue
		}
		switch sessionM.Career.ReportType {
		case "web", "custom":
			report.URL = fmt.Sprintf(
				"%s/web-report?reportId=%d&careerId=%d",
				variable.Config.App.Prefix, sessionM.ID, sessionM.CareerID,
			)
		default:
			report.URL = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + reportM.Url
		}
		report.Status = reportM.Status
		report.BeginDate = sessionM.CreatedAt
		report.Duration = date.SecondsSwitchTime(int(sessionM.FinishAt.Unix() - sessionM.CreatedAt.Unix()))
		report.CareerName = sessionM.Career.Name
		report.TotalScore = int(sessionM.TotalScore)
		report.FinishTime = sessionM.FinishAt
		report.ReportType = sessionM.Career.ReportType
		if strings.HasSuffix(reportM.Url, ".pdf") {
			report.ReportType = "pdf"
			report.URL = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + reportM.Url
		}
		report.IsShared = sessionM.IsShared
		report.ReportIsSync = sessionM.IsSync
		u := new(tables.User)
		variable.DB.MySQL.Select("IsSync").First(u, uid)
		if !u.IsSync {
			report.ReportIsSync = false
		}
		report.AgentIsSync = agent.IsSync
		reports = append(reports, report)
	}
	return reports, nil
}

// 语言表述评分
func FetchLanguageComment(text string) float64 {
	textNum := len(text)
	if textNum >= 700 {
		return 100.00
	} else if textNum >= 600 && textNum <= 699 {
		return 90.00
	} else if textNum >= 400 && textNum <= 599 {
		return 75.00
	} else if textNum >= 200 && textNum <= 399 {
		return 50.00
	} else if textNum >= 50 && textNum <= 199 {
		return 30.00
	}
	return 0.00
}

//func FindReportBySessionId(sessionId int) (*tables.Session, error) {
//	var report tables.Session
//	err := variable.DB.MySQL.First(&report, sessionId).Error
//	if err != nil {
//		return nil, err
//	}
//	return &report, nil
//}

//func CreateReport(report *tables.Session) error {
//	if report.SessionID <= 0 {
//		return errors.New("SessionID Undefined")
//	}
//
//	if report.UserID <= 0 {
//		return errors.New("UserId Undefined")
//	}
//
//	err := variable.DB.MySQL.Create(report).Error
//	if err != nil {
//		return err
//	}
//
//	return nil
//}

func SaveReport(report *tables.Session) error {
	if report.ID <= 0 {
		return fmt.Errorf("SessionID Undefined")
	}

	if report.UserID <= 0 {
		return fmt.Errorf("UserId Undefined")
	}

	err := variable.DB.MySQL.Model(&tables.Session{}).Where("id=?", report.ID).Updates(map[string]interface{}{"status": report.Status, "url": report.Url}).Error
	if err != nil {
		return err
	}

	return nil
}

func RemoveReportBySessionId(sessionId int) error {
	//err := variable.DB.MySQL.Where("session_id = ?", sessionId).Delete(&tables.Report{}).Error
	err := variable.DB.MySQL.Where("id=?", sessionId).Updates(tables.Session{Url: "", Status: 0}).Error

	if err != nil {
		return err
	}

	return nil
}

// 调用要点 | 关键词评分接口
func FetchQScore(ansText string, kwList []string) float64 {
	if len(ansText) == 0 || len(kwList) == 0 {
		return 0.00
	}
	scr := &model.ScoreReq{AnsText: ansText, KwList: kwList}
	reqData, _ := json.Marshal(scr)
	resp, err := http.Post(
		variable.Config.Services.QScore,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("评分接口调用失败: " + err.Error())
		return 0.00
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	sr := model.ScoreResp{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &sr)
	return sr.Score * 100
}

func FetchFocusTopicScore(quesText, ansText string) float64 {
	if len(ansText) == 0 || len(quesText) == 0 {
		return 0.00
	}
	scr := &model.ScoreFocusTopic{AnsText: ansText, QuesText: quesText}
	reqData, _ := json.Marshal(scr)
	resp, err := http.Post(
		variable.Config.Services.FocusThemeScore,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("围绕主题评分接口调用失败: " + err.Error())
		return 0.00
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "围绕主题评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "围绕主题评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	sr := model.ScoreResp{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &sr)
	return sr.Score * 100
}

func FetchLogicScore(quesText, ansText string) float64 {
	if len(ansText) == 0 || len(quesText) == 0 {
		return 0.00
	}
	scr := &model.ScoreFocusTopic{AnsText: ansText, QuesText: quesText}
	reqData, _ := json.Marshal(scr)
	resp, err := http.Post(
		variable.Config.Services.LogicScore,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("逻辑评分接口调用失败: " + err.Error())
		return 0.00
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "逻辑评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "逻辑评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	sr := model.ScoreResp{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &sr)
	return sr.Score * 100
}

func FetchLabelsCache(ctx *gin.Context, jobName, ansText string) string {
	if jobName == "通用岗位" {
		jobName = "通用能力"
	}
	data := map[string]string{
		"job_name":   jobName,
		"input_text": ansText,
	}
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		variable.Config.Services.PartLabelsCache,
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		log.Logger.ErrorF(ctx, "每道题测评评分接口调用失败: "+err.Error())
		return err.Error()
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return err.Error()
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return errMsg
	}
	b, _ := json.Marshal(res["data"])
	return string(b)
}

func FetchEvalByLabelsZhuanxiang(ctx *gin.Context, jobName string, labelExtractList, analyzeLables, testLabels []interface{}) string {
	if jobName == "通用岗位" {
		jobName = "通用能力"
	}
	data := map[string]interface{}{
		"job_name":           jobName,
		"label_extract_list": labelExtractList,
		"analyze_lables":     analyzeLables,
		"test_labels":        testLabels,
	}
	fmt.Println(data)
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		variable.Config.Services.EvalByLabelsZhuanxiang,
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		log.Logger.ErrorF(ctx, "每道题测评评分接口调用失败: "+err.Error())
		return err.Error()
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return err.Error()
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return errMsg
	}
	b, _ := json.Marshal(res["data"])
	return string(b)
}
func FetchDataMask(ctx *gin.Context, ansText string) string {
	data := map[string]string{
		"input_text": ansText,
	}
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		variable.Config.Services.DataMask,
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		log.Logger.ErrorF(ctx, "transfer data mask is error, : "+err.Error())
		return err.Error()
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBodyCtx(ctx, resp, &res)
	if err != nil {
		errMsg := "data mask is error," + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return err.Error()
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "data mask analysis is error" + err.Error()
		log.Logger.ErrorF(ctx, errMsg)
		return errMsg
	}
	b, _ := json.Marshal(res["data"])
	return string(b)
}

func FetchEvaluationScore(reqData []byte) *model.LabelEvaluate {
	log.ZapLogger.Error("evaluation score: " + string(reqData))
	var a map[string]interface{} = make(map[string]interface{}, 0)
	json.Unmarshal(reqData, &a)
	if jobName, ok := a["job_name"]; ok {
		if jobName == "通用岗位" {
			a["job_name"] = "通用能力"
		}
		reqData, _ = json.Marshal(a)
	}

	resp, err := http.Post(
		variable.Config.Services.EvaluateScore,
		"application/json",
		bytes.NewReader(reqData),
	)
	fmt.Println(variable.Config.Services.EvaluateScore)
	fmt.Println(string(reqData))
	if err != nil {
		log.ZapLogger.Error("测评评分接口调用失败: " + err.Error())
		return &model.LabelEvaluate{}
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return &model.LabelEvaluate{}
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "测评评分接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return &model.LabelEvaluate{}
	}
	sr := model.LabelEvaluate{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &sr)
	sr.ReqData = string(reqData)
	return &sr
}

// 语气词得分
func FetchMood(ansText string) float64 {
	params := map[string]string{"text": ansText}
	reqData, _ := json.Marshal(params)
	resp, err := http.Post(
		variable.Config.Services.MoodURL,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("语气词占比接口调用失败: " + err.Error())
		return 0.00
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "语气词占比接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "语气词占比接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	mr := model.ScoreResp{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &mr)
	return mr.Score * 100
}

// 语调气场
func FetchEmotion(ansAudioUrl string) float64 {
	params := map[string]string{"text": ansAudioUrl}
	reqData, _ := json.Marshal(params)
	resp, err := http.Post(
		variable.Config.Services.EmotionUrl,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("语调气场接口调用失败: " + err.Error())
		return 0.00
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "语调气场接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "语调气场接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return 0.00
	}
	mr := model.ScoreResp{}
	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &mr)
	return mr.Score * 100
}

// 人物性格
func FetchCharacter(ansText string) (model.CharacterResp, error) {
	mr := model.CharacterResp{}
	params := map[string]string{"text": ansText}
	reqData, _ := json.Marshal(params)
	resp, err := http.Post(
		variable.Config.Services.CharacterUrl,
		"application/json",
		bytes.NewReader(reqData),
	)
	if err != nil {
		log.ZapLogger.Error("人格测评接口调用失败: " + err.Error())
		return mr, err
	}
	if resp != nil {
		defer resp.Body.Close()
	}
	res := make(map[string]interface{})
	err = tools.ReadResponseBody(resp, &res)
	if err != nil {
		errMsg := "人格测评接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return mr, err
	}
	if code, _ := res["code"].(int64); code != 0 {
		errMsg := "人格测评接口响应结果解析失败" + err.Error()
		log.ZapLogger.Error(errMsg)
		return mr, err
	}

	b, _ := json.Marshal(res["data"])
	_ = json.Unmarshal(b, &mr)
	return mr, nil
}

// 生成报告
func GenerateReport(ctx *gin.Context, sessionId string, isMark bool) error {
	sid, err := strconv.Atoi(sessionId)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code": 500,
			"data": struct{}{},
			"msg":  "场次ID不合法",
		})
		return fmt.Errorf("场次ID不合法")
	}
	session, err := services.FindSessionById(sid)
	if err != nil {
		return err
	}
	if session.FinishAt.Format("2006-01-02 15:04:05") == "0001-01-01 00:00:00" {
		session.FinishAt = time.Now()
	}
	session.Status = tables.ProStatus
	if err := variable.DB.MySQL.Model(session).Updates(session).Error; err != nil {
		return err
	}
	if session.User == nil {
		return fmt.Errorf("当前用户不存在")
	}
	// check 所有的数据是否全部生成
	// variable.DB.Redis.RPush(common.RedisSessionMp3Queue, sid)
	// log.Logger.InfoMsgF(ctx, fmt.Sprintf("info:写入RedisSessionMp3Queue队列:%d", sid))

	// 屏蔽语音
	var rq []tables.RealQues
	d := variable.DB.MySQL.Model(tables.RealQues{}).Where("session_id = ? and current_tag = 1", sessionId).Find(&rq)
	if d.Error != nil {
		log.Logger.ErrorMsgF(ctx, "pcm trans, get question is error ")
	}

	if session.CareerID != 2 {
		for i := 0; i < len(rq); i++ {
			_, err := new(MaskService).MaskWords(ctx, int(rq[i].ID))
			if err != nil {
				log.Logger.InfoMsgF(ctx, fmt.Sprintf("id:%d, err:%s", rq[i].ID, err.Error()))
			}
		}
	}

	// 过滤是否生成报告
	var p []string
	cc, _ := new(tables.CommonConf).FetchByTypeKey(tables.ConfKeyUserNoReport, tables.UserNoReport)
	dec := json.NewDecoder(strings.NewReader(cc[0].ConfValue))
	dec.Decode(&p)
	logger := &log.MyLogger{
		Zlog: log.InitLogger(fmt.Sprintf("logs/%d_report.log", session.ID)),
	}
	saveFunc := func(data []byte, upType string) {
		saveName := function.CreateMD5(fmt.Sprintf("%d%s", sid, time.Now().String())) + "." + upType
		timeFormat := time.Now().Format("2006-01-02")
		accessPath := "/static/reports/" + timeFormat + "/" + saveName
		err = sdk.IOput(data, variable.Config.UfsInfo.BucketPrefix+accessPath, "application/"+upType)
		if err != nil {
			_ = RemoveReportBySessionId(sid)
			logger.ErrorF(ctx, fmt.Sprintf("Json Upload Error: %s", err.Error()))
			return
		}
		if tools.Contains(p, session.UserPhone) {
			session.Status = tables.IoStatus
		} else {
			session.Status = tables.SucStatus
		}
		session.Url = accessPath
		_ = SaveReport(session)
	}
	switch session.Career.ReportType {
	case "web", "custom":
		reportData := &web_report.ReportData{
			Ctx: ctx, Session: session,
			Logger: logger,
		}
		defaultReport := &web_report.DefaultWebReport{ReportData: reportData}
		switch {
		case session.CareerID == tables.QCommonId:
			reportData.IWebReport = &web_report.CommonWebReport{DefaultWebReport: defaultReport}
		case session.Career.ReportType == "custom":
			// 查询职业是否已经生成标签
			var labels *tables.CustomLabel
			err = variable.DB.MySQL.Model(&tables.CustomLabel{}).Where(
				"status != ? and job_name=?", 4, session.CareerName,
			).First(&labels).Error
			logger.Info(fmt.Sprintf("err:%+v labels:%+v, name:%s", err, labels, session.CareerName))
			if labels != nil && labels.ID != 0 {
				reportData.IWebReport = &web_report.CommonWebReport{DefaultWebReport: defaultReport}
			} else {
				reportData.IWebReport = &web_report.CustomWebReport{DefaultWebReport: defaultReport}
			}
		case session.CareerID == tables.BankTrainee:
			reportData.IWebReport = &web_report.BankManagementStudentWebReport{DefaultWebReport: defaultReport}
		default:
			reportData.IWebReport = defaultReport
		}
		go func() {
			defer tools.RecoverGoroutine()
			if err := reportData.Generate(); err != nil {
				logger.ErrorF(ctx, err.Error())
				return
			}
			jsonData, err := json.Marshal(reportData.Data)
			if err != nil {
				logger.ErrorF(ctx, err.Error())
				return
			}
			logger.InfoF(ctx, string(jsonData))
			saveFunc(jsonData, "json")
		}()
	case "pdf", "":
		go func() {
			defer tools.RecoverGoroutine()
			pdfg, err := wkhtmltopdf.NewPDFGenerator()
			if err != nil {
				_ = RemoveReportBySessionId(sid)
				logger.ErrorF(ctx, fmt.Sprintf("New PDF Generatoris error: %s", err.Error()))
				return
			}
			downPage := ""

			if isMark {
				downPage = fmt.Sprintf("http://127.0.0.1%s/practice/session/%s/report?mark=true",
					variable.Config.App.Port, sessionId)
			} else {
				downPage = fmt.Sprintf("http://127.0.0.1%s/practice/session/%s/report?mark=false",
					variable.Config.App.Port, sessionId)
			}
			page := wkhtmltopdf.NewPage(downPage)
			page.FooterRight.Set("[page]")
			page.FooterFontSize.Set(10)
			page.Allow.MarshalJSON()
			page.Zoom.Set(1.32015)
			pdfg.MarginBottom.Set(0)
			pdfg.MarginTop.Set(0)
			pdfg.MarginLeft.Set(0)
			pdfg.MarginRight.Set(0)
			pdfg.AddPage(page)
			err = pdfg.Create()
			if err != nil {
				_ = RemoveReportBySessionId(sid)
				logger.ErrorF(ctx, fmt.Sprintf("New PDF Create error: %s", err.Error()))
				return
			}
			saveFunc(pdfg.Bytes(), "pdf")
		}()
	case "none":
		session.Status = tables.SucStatus
		_ = SaveReport(session)
	default:
		logger.ErrorMsgF(ctx, "岗位报告类型有误，目前只支持 json/pdf")
		return fmt.Errorf("岗位报告类型有误，目前只支持 json/pdf")
	}
	session.User.TrailCount -= 1
	if session.User.TrailCount < 0 {
		session.User.TrailCount = 0
	}
	variable.DB.MySQL.Select("TrailCount").Save(session.User)
	return nil
}

type NewReportClickReq struct {
	Type string `json:"type" form:"type"`
	Uid  int
}

func NewReportClick(req *NewReportClickReq) error {
	if req.Type == "icon" {
		return variable.DB.Redis.Set(fmt.Sprintf(common.RedisNewReportIconKey, req.Uid), "1", time.Hour*24*45).Err()
	}
	if req.Type == "banner" {
		return variable.DB.Redis.Set(fmt.Sprintf(common.RedisNewReportBannerKey, req.Uid), "1", time.Hour*24*45).Err()
	}
	return nil
}

type GetReportResp struct {
	Status    uint   `json:"status"` // 0-生成中 1-生成完成
	SessionId uint   `json:"session_id"`
	ReportUrl string `json:"report_url"`
}

func GetReport(ctx *gin.Context, sessionId string) (*GetReportResp, error) {
	resp := &GetReportResp{}
	var session tables.Session
	d := variable.DB.MySQL.Model(&tables.Session{}).Where("id = ?", sessionId).Preload("Career").First(&session)
	if d.Error != nil {
		return nil, fmt.Errorf("get session error:%+v", d.Error)
	}
	if session.Status != 1 || session.Url == "" {
		resp.Status = 0
		return resp, nil
	}
	reportUrl := fmt.Sprintf("%s/web-report/?careerId=%d&debug=1&reportId=%d", variable.Config.App.Domain, session.CareerID, session.ID)
	if session.Career.ReportType == "pdf" {
		reportUrl = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + session.Url
	}
	resp.Status = 1
	resp.ReportUrl = reportUrl
	resp.SessionId = session.ID
	return resp, nil
}
